﻿using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.ServiceModel;
using System.ServiceModel.Description;
using dis.sys.hw1.ClientProxy;
using dis.sys.hw1.Contract;
using dis.sys.hw1.Service;
using ZooKeeperNet;

namespace dis.sys.hw1.HotelServiceHost
{
    class Program
    {
        private static readonly ServiceLog _log = new ServiceLog(typeof(Program), true);
        private const int DelegatePortArg = 0;
        private const int InternalPortArg = 1;
        private const int SearchServiceAddressArg = 2;
        private const int InputDataArg = 3;
        private const int LogFileArg = 4;
        private const string ZooKeeperConfig = "zookeeper.conf";

        /*
         * hotel side service entry point
         */
        static void Main(string[] args)
        {
            if (args.Count() < 5) 
            {
                Console.WriteLine("Invalid usage, please use: HotelService.exe <delegate port> <internal port> <hotel search server URI #2> <input file name> <log file name>");
                return;
            }

            string delegateEndPointAddress = "http://localhost:" + args[DelegatePortArg] + "/Services/DelegateHotelService";
            string internalEndPointAddress = "http://localhost:" + args[InternalPortArg] + "/Services";
            var replicator = ConfigureZooKeeper();

            using (var host = new ServiceHost(new HotelService(args[InputDataArg], int.Parse(args[DelegatePortArg]), int.Parse(args[InternalPortArg]), replicator, args[SearchServiceAddressArg]), new Uri(internalEndPointAddress)))
            {
                var smb = new ServiceMetadataBehavior
                    {
                        HttpGetEnabled = true, 
                        MetadataExporter = {PolicyVersion = PolicyVersion.Policy15}
                    };
                host.Description.Behaviors.Add(smb);
                // Add MEX endpoint
                host.AddServiceEndpoint(
                  ServiceMetadataBehavior.MexContractName,
                  MetadataExchangeBindings.CreateMexHttpBinding(),
                  "mex"
                );

                host.Description.Behaviors.Add(new Logging(args[LogFileArg]));
                host.AddServiceEndpoint(typeof(IHotelService), new BasicHttpBinding(), "HotelService");
                host.AddServiceEndpoint(typeof(IDelegateHotelService), new BasicHttpBinding(), new Uri(delegateEndPointAddress));
                var service = host.SingletonInstance as HotelService;

                host.Open();

                _log.Info("Endpoint opened at: " + internalEndPointAddress + "/HotelService");

            
                _log.Info("Endpoint opened at: " + delegateEndPointAddress + "/DelegateHotelService");


                Debug.Assert(service != null, "service != null");

                service.Init();

                Console.ReadKey();

                try
                {
                    if (service.GetOtherActiveServers().Count() == 0)
                    {
                        Debug.Assert(service != null, "service != null");
                        var httpEndpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(IRegistrationService)),
                        new BasicHttpBinding(), new EndpointAddress((args[SearchServiceAddressArg].StartsWith("http://") ? "" : "http://") + args[SearchServiceAddressArg]));
                        var proxy = new HotelRegistrationProxy(httpEndpoint);
                        proxy.Unregister(service.Alliance);
                    }
                }
                catch (Exception)
                {
                    _log.Error("Search Service Unavailable");
                }
            }
        }

        private static ZooKeeper ConfigureZooKeeper()
        {
            string line = new FileInfo(ZooKeeperConfig).OpenText().ReadLine();
            return new ZooKeeper(line, new TimeSpan(0, 0, 1000), null);
        }
    }
}
